namespace Ex
{
    using System.Diagnostics;
    using KeraLua;

    public class ExCsClassFunction : ExCsFunction
    {

        public ExCsClassFunction(
            EnvLua lua,
            string func_name,
            Func<IndefiniteVarType, IndefiniteVarType> func,
            UsableLuaType[] param_type
            ) : base(lua, func_name, func, new UsableLuaType[] {UsableLuaType.csobject}.Concat(param_type).ToArray())
        {
        }

        public ExCsClassFunction(
            EnvLua lua,
            string func_name,
            Func<IndefiniteVarType, IndefiniteVarType> func
            ) : base(lua, func_name, func)
        {
        }


        protected override void ExceptionHandle(Action action, string addon_msg)
        {
            try
            {
                action();
            }
            catch (Exception e)
            {
                if (e is InvalidOperationException || e is InvalidDataException)
                {
                    lock (env)
                    {
                        if (e.Data.Contains("arg_order") && e.Data["arg_order"] is int order && order == 0 && addon_msg == "parameter error")
                        {
                            env.Current.Error(string.Format("first param must be csobject, please use function form like obj:{0}(params...)", func_name), true);
                        }
                        else
                        {
                            var order_msg = e.Data.Contains("arg_order") ? string.Format(" at {0}", e.Data["arg_order"]) : "";
                            env.Current.Error(addon_msg + order_msg + '\n' + e.Message);
                        }
                    }
                }
                else
                {
                    throw;
                }
            }
        }

        // protected override LuaFunction CreateLuaFunction(Func<IndefiniteVarType> param_getter)
        // {
        //     return target =>
        //     {
        //         IndefiniteVarType? param = null, ret = null;
        //         ExceptionHandle(
        //             () =>
        //             {
        //                 object obj = env.FetchObjectFromLuaStack(UsableLuaType.csobject);
        //                 var old_param = param_getter();
        //                 var new_param = new object[old_param.Count + 1];
        //                 new_param[0] = obj;
        //                 Array.Copy(old_param.Value, 0, new_param, 1, old_param.Count);
        //                 param = IndefiniteVarType.FromArray(new_param);

        //             },
        //             "parameter error"
        //         );
        //         Debug.Assert(param != null);
        //         ExceptionHandle(
        //             () => ret = func(param),
        //             "running error"
        //         );
        //         Debug.Assert(ret != null);
        //         ret.PushToLuaStack(env);
        //         return ret.Count;
        //     };
        // }

    }
}